#ifndef HEAP_TIMER_H
#define HEAP_TIMER_H

#include <chrono>
#include <cstddef>
#include <functional>
#include <unordered_map>
#include <vector>

typedef std::function<void()> TimeoutCallBack;
typedef std::chrono::high_resolution_clock Clock;
typedef std::chrono::milliseconds MS;
typedef Clock::time_point TimeStamp;

// 时间节点
struct TimerNode {
    int id; // 唯一标识符，用于标识不同的定时器
    TimeStamp expires; // 到期时间
    TimeoutCallBack cb; // 到期后执行的函数
    bool operator<(const TimerNode& t) {
        return expires < t.expires;
    }
};

class HeapTimer {
public:
    HeapTimer() {
        heap_.reserve(64);
    }

    ~HeapTimer() {
        clear();
    }

    // 更改某个定时器的到期时间
    void adjust(int id, int newExpires);
    
    // 执行定时器的回调函数
    void doWork(int id);

    // 添加定时器
    void add(int id, int timeout, const TimeoutCallBack& cb);

    // 清除堆
    void clear();

    // 更新时间并检查定时器的状态
    // 会遍历堆找到已经到时的计时器
    void tick();
    
    // 移除堆顶计时器（最早到期的计时器）
    void pop();

    // 获取下一个定时器的到期时间
    int GetNextTick();
private:
    // 删除指定索引的堆节点
    void del_(size_t i);

    // 从i开始，向上进行堆化
    void siftup_(size_t i);

    // 从index开始，向下进行堆化
    bool siftdown_(size_t index, size_t n);

    // 交换两个索引的节点
    void SwapNode_(size_t i, size_t j);

    // 堆（小顶堆，最顶上是最早到期的节点）
    std::vector<TimerNode> heap_;

    // 建立node到索引的映射
    std::unordered_map<int, size_t> ref_;
};

#endif